package com.wasion.pwportable.protocol.p2;

import static com.wasion.core.util.ConvertInXBaseUtil.binary2Decimal;
import static com.wasion.core.util.ConvertInXBaseUtil.byte2Decimal;
import static com.wasion.core.util.ConvertInXBaseUtil.byte2Hex;
import static com.wasion.core.util.ConvertInXBaseUtil.decimal2Binary;
import static com.wasion.core.util.ConvertInXBaseUtil.hex2Decimal;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import android.R.integer;

import com.wasion.core.util.ConvertInXBaseUtil;
import com.wasion.pwportable.protocol.p2.FrameFieldsLength.AsduPublicAddrLengthEnum;
import com.wasion.pwportable.protocol.p2.FrameFieldsLength.COTLengthEnum;
import com.wasion.pwportable.protocol.p2.FrameFieldsLength.ControlFieldLengthEnum;
import com.wasion.pwportable.protocol.p2.FrameFieldsLength.InfoObjectAddrLengthEnum;
import com.wasion.pwportable.protocol.p2.FrameFieldsLength.LinkAddrLengthEnum;

/**
 * 
 * @ClassName: VariableFrame
 * @Description: IEC101和IEC104的可变帧结构定义
 * @author 高意
 * @date Apr 13, 2016 4:05:37 PM
 * 
 *       启动字符(68H)---------1字节<br>
 *       报文长度L-------------1字节<br>
 *       报文长度L-------------1字节(或无)<br>
 *       启动字符(68H)---------1字节(或无)<br>
 *       控制域C---------------1字节<br>
 *       地址域A---------------2字节<br>
 *       应用服务数据单元ASDU---长度可变<br>
 *       --{<br>
 *       ----类型标识符------------1字节<br>
 *       ----可变结构限定词---------1字节(singleOrQueue:0: 单个；1: 顺序 number：数目)<br>
 *       ----传送原因--------------1字节<br>
 *       ----ASDU公共地址----------2字节<br>
 *       ----信息对象<br>
 *       ----{<br>
 *       --------信息对象地址-------2字节<br>
 *       --------信息元素集 ---------1字节(或2字节或3字节或5字节或无)<br>
 *       --------信息对象时标-------7字节(或无)<br>
 *       ----}<br>
 *       --}<br>
 *       帧校验和CS------------1字节(或无)<br>
 *       结束字符(16H) --------1字节(或无)<br>
 * 
 * 
 */
public class VariableFrame {

	private String startCharacter = "68"; // 起始字符68

	private int length; // 报文长度L

	private String controlField; // 控制域C

	private String addressField; // 地址域A

	/** ------应用服务数据单元ASDU，Begin------ */
	private int typeIdentity; // 类型标识符TI

	// 可变帧长限定词VSQ 分成 sq + number
	// 0: 单个；1: 顺序
	private int singleOrQueue;

	private int number; // 数目

	private int cause; // 传送原因COT

	private String asduPublicAddr; // ASDU公共地址

	private List<InfoObject> infoObjs = new ArrayList<InfoObject>(); // 信息对象集合

	private RecordingData recordingData; // 故障录波

	private FileInfoObject fileInfoObject; // 文件信息对象

	private SectionInfoObject sectionInfoObject; // 节信息对象

	private PieceDataInfoObject pieceDataInfoObject; // 段数据信息对象

	private RemoteControlInfoObject remoteControlInfoObject; // 遥控信息对象

	private FileListInfoObject fileListInfoObject; // 文件目录信息对象

	private CurrSettingArea currSettingArea; // 终端当前的定值区信息对象

	private List<Parameter> parameters = new ArrayList<Parameter>(); // 定值参数对象集合

	// 文件名长度，考虑终端版本的兼容性，终端的录波上报文件长度有8个字节和32个字节，现根据报文长度计算获得
	private int fileNameLen = FileInfoObject.FILE_NAME_LENGTH;
	/** ------应用服务数据单元ASDU，End------ */

	private String sumCheck; // 帧校验和CS

	private String finalCharacter = "16"; // 结束字符16

	// 报文
	private byte[] data;
	// 报文解析偏移量
	private int offset;

	public VariableFrame(byte[] data, ProtocolEnum.TypeEnum type,
			ControlFieldLengthEnum controlFieldLen,
			LinkAddrLengthEnum linkAddrLen,
			AsduPublicAddrLengthEnum asduAddrLen, COTLengthEnum cotLen,
			InfoObjectAddrLengthEnum infoObjAddrLen) throws Exception {

		this.data = data;
		this.offset = 0;

		// 起始字符
		parseStartCharacter();

		// 报文长度
		parseLength();

		// 控制域
		parseControlField(type, controlFieldLen);

		// 地址域
		parseAddressField(type, linkAddrLen);

		// 类型标识
		parseTypeIdentity();

		// 可变结构限定词
		parseVarStructQualifier();

		// 传送原因
		parseCause(cotLen);

		// 应用服务数据单元公共地址
		parseASDU(asduAddrLen);

		TypeIndentityEnum tiEnum = TypeIndentityEnum
				.getTypeIndentityEnum(typeIdentity);
		switch (tiEnum) {
		case SINGLE_POINT_INFO_TI: // ti<1> 单点遥信（M_SP_NA_1）
		case DOUBLE_POINT_INFO_TI: // ti<3> 双点遥信
		case SINGLE_POINT_INFO_TIMESTAMP_TI: // ti<30>带CP56Time2a时标的单点信息
		case DOUBLE_POINT_INFO_TIMESTAMP_TI: // ti<31>带CP56Time2a时标的双点信息
			parseYX(infoObjAddrLen, tiEnum);
			break;

		case MEASURED_VAL_NORMALIZE_TI: // ti<9> 归一化测量值（M_ME_NA_1）
		case MEASURED_VAL_FLOAT_TI: // ti<13> 测量值，短浮点数
		case MEASURED_VAL_NORMALIZE_TIMESTAMP_TI: // ti<34>测量值，带时标CP56Time2a的归一化值
		case MEASURED_VAL_FLOAT_TIMESTAMP_TI: // ti<36>测量值，带时标CP56Time2a的短浮点数
		case MEASURED_VAL_ZJ_PDJKXL_TI: // ti<21>测量值，浙江配电架空线路数据采集
			parseYC(infoObjAddrLen, tiEnum);
			break;

		case FAULT_RECORDING_DATA_ZJ_PDJKXL_TI: // ti<152>故障录波主动上报，浙江配电架空线路数据采集
			parseRecordingData(infoObjAddrLen);
			break;
		case READY_FILE: // ti<120>文件准备就绪
			parseFileReady(infoObjAddrLen);
			break;
		case READY_SECTION: // ti<121>节准备就绪
			parseSectionReady(infoObjAddrLen);
			break;
		case PIECE_DATA: // ti<125>段数据
			parsePieceData(infoObjAddrLen);
			break;
		case LAST_SECTION_OR_PIECE: // ti<123>最后的节，最后的段
			parseLastSectionOrPiece(infoObjAddrLen);
			break;
		case FILE_LIST: // ti<126>文件目录
			parseFileList(infoObjAddrLen);
			break;
		case REMOTE_CONTROL_TI: // 遥控
			parseRemoteControl(infoObjAddrLen);
			break;
		case CLOCK_SYN_TI: // 时钟同步
			parseSyncTime(infoObjAddrLen);
			break;
		case SINGLE_PARAM_RD: // 读单个参数
		case SINGLE_PARAM_WR: // 预置/激活单个参数
			parseSingleParamReadAndWrite(infoObjAddrLen);
			break;
		case SETTING_AREA_RD: // 读当前定值区号
			parseSettingAreaRead(infoObjAddrLen);
			break;
		case SETTING_AREA_WR: // 切换定值区号
			parseSettingAreaWrite(infoObjAddrLen);
			break;
		case PARAMS_RD: // 读多个/全部参数和定值
			parseParametersRead(infoObjAddrLen);
			break;
		case INIT_TI: // 初始化结束
			break;
		case ALL_DATA_COLLECT_TI: // 全召唤
			break;
		default:
			throw new RuntimeException("数据错误, 类型标识符TI[ " + typeIdentity
					+ " ]未定义!");
		}

		// 帧校验和
		parseSumCheck(type);

		// 结束字符
		parseFinalCharacter(type);
	}

	/**
	 * 
	 * @Title: parseYX
	 * @Description: 遥信解析
	 * @param
	 * @return
	 * @throws
	 */
	protected void parseYX(InfoObjectAddrLengthEnum infoObjAddrLen,
			TypeIndentityEnum tiEnum) {

		int addr = 0;
		for (int i = 0; i < number; i++) {

			InfoObject object = new InfoObject();
			if (0 == singleOrQueue || 0 == i) {
				switch (infoObjAddrLen) {
				case LENGTH_INFO_ADDR_2:
					addr = byte2Decimal(data[offset + 1]) * 256
							+ byte2Decimal(data[offset]);
					offset += 2;
					break;
				case LENGTH_INFO_ADDR_3:
					addr = byte2Decimal(data[offset + 2]) * 256 * 256
							+ byte2Decimal(data[offset + 1]) * 256
							+ byte2Decimal(data[offset]);
					offset += 3;
					break;
				}
			} else {
				addr++;
			}

			object.setAddr(addr);
			object.setType(1);

			switch (tiEnum) {
			case SINGLE_POINT_INFO_TI: // 单点信息
			case DOUBLE_POINT_INFO_TI: // 双点信息

				object.setValue(Integer.toString(byte2Decimal(data[offset])));
				offset++;

				break;
			case SINGLE_POINT_INFO_TIMESTAMP_TI: // 带CP56Time2a时标的单点信息
			case DOUBLE_POINT_INFO_TIMESTAMP_TI: // 带CP56Time2a时标的双点信息

				object.setValue(Integer.toString(byte2Decimal(data[offset])));
				offset++;

				byte[] newData = Arrays.copyOfRange(data, offset, offset + 7);
				object.setTimeStamp(parseTimestamp(newData));
				offset += 7;

				break;
			default:
				break;
			}

			infoObjs.add(object);
		}
	}

	/**
	 * 
	 * @Title: parseYC
	 * @Description: 遥测解析
	 * @param
	 * @return
	 * @throws
	 */
	protected void parseYC(InfoObjectAddrLengthEnum infoObjAddrLen,
			TypeIndentityEnum tiEnum) {

		int addr = 0;
		for (int i = 0; i < number; i++) {
			InfoObject object = new InfoObject();
			if (0 == singleOrQueue || 0 == i) {
				switch (infoObjAddrLen) {
				case LENGTH_INFO_ADDR_2:
					addr = byte2Decimal(data[offset + 1]) * 256
							+ byte2Decimal(data[offset]);
					offset += 2;
					break;
				case LENGTH_INFO_ADDR_3:
					addr = byte2Decimal(data[offset + 2]) * 256 * 256
							+ byte2Decimal(data[offset + 1]) * 256
							+ byte2Decimal(data[offset]);
					offset += 3;
					break;
				}
			} else {
				addr++;
			}

			object.setAddr(addr);
			object.setType(2);

			int symbol = 0;
			int oriValue = 0;
			String value = "";
			byte[] newData;
			switch (tiEnum) {
			case MEASURED_VAL_NORMALIZE_TI: // 归一化测量值（M_ME_NA_1）

				symbol = data[offset + 1] >> 8; // 最高位为1表示负数，为0表示正数
				oriValue = byte2Decimal(data[offset + 1]) * 256
						+ byte2Decimal(data[offset]);
				value = (symbol == -1 ? -1 * (65536 - oriValue) : oriValue)
						+ "";

				object.setValue(value);
				offset += 2;

				object.setDescripWords(byte2Hex(data[offset]));
				offset++;
				break;
			case MEASURED_VAL_FLOAT_TI: // 测量值，短浮点数
				value = Double.toString(ConvertInXBaseUtil
						.decodeShortFloatingNumber(ConvertInXBaseUtil
								.byte2Hex(data[offset + 3])
								+ ConvertInXBaseUtil.byte2Hex(data[offset + 2])
								+ ConvertInXBaseUtil.byte2Hex(data[offset + 1])
								+ ConvertInXBaseUtil.byte2Hex(data[offset])));

				object.setValue(value);
				offset += 4;

				object.setDescripWords(byte2Hex(data[offset]));
				offset++;
				break;

			case MEASURED_VAL_FLOAT_TIMESTAMP_TI: // 测量值，带时标CP56Time2a的短浮点数
				value = Double.toString(ConvertInXBaseUtil
						.decodeShortFloatingNumber(ConvertInXBaseUtil
								.byte2Hex(data[offset + 3])
								+ ConvertInXBaseUtil.byte2Hex(data[offset + 2])
								+ ConvertInXBaseUtil.byte2Hex(data[offset + 1])
								+ ConvertInXBaseUtil.byte2Hex(data[offset])));

				object.setValue(value);
				offset += 4;

				object.setDescripWords(byte2Hex(data[offset]));
				offset++;

				newData = Arrays.copyOfRange(data, offset, offset + 7);
				object.setTimeStamp(parseTimestamp(newData));
				offset += 7;

				break;
			case MEASURED_VAL_NORMALIZE_TIMESTAMP_TI: // 测量值，带时标CP56Time2a的归一化值
			case MEASURED_ALARM_ZJ_PDJKXL_TI: // 遥测告警，浙江架空线路数据采集

				symbol = data[offset + 1] >> 8; // 最高位为1表示负数，为0表示正数
				oriValue = byte2Decimal(data[offset + 1]) * 256
						+ byte2Decimal(data[offset]);
				value = (symbol == -1 ? -1 * (65536 - oriValue) : oriValue)
						+ "";

				object.setValue(value);
				offset += 2;

				object.setDescripWords(byte2Hex(data[offset]));
				offset++;

				newData = Arrays.copyOfRange(data, offset, offset + 7);
				object.setTimeStamp(parseTimestamp(newData));
				offset += 7;

				break;

			case MEASURED_VAL_ZJ_PDJKXL_TI:

				if (addr >= 1793 && addr < 1903) {// 架空线路遥测数据上报帧(起始信息体地址01H
					// 07H, 1793)
					symbol = data[offset + 1] >> 8; // 最高位为1表示负数，为0表示正数
					oriValue = byte2Decimal(data[offset + 1]) * 256
							+ byte2Decimal(data[offset]);
					value = (symbol == -1 ? -1 * (65536 - oriValue) : oriValue)
							+ "";

					object.setValue(value);
					offset += 2;

					object.setDescripWords(byte2Hex(data[offset]));
					offset++;
				} else if (addr >= 1903) {// 电缆线路遥测数据上报帧(起始信息体地址6FH
					// 07H, 1903)
					// 接地电流放大装置遥测数据上报帧(起始信息体地址ABH 07H,
					// 1963)
					symbol = data[offset + 1] >> 8; // 最高位为1表示负数，为0表示正数
					oriValue = byte2Decimal(data[offset + 1]) * 256
							+ byte2Decimal(data[offset]);
					value = (symbol == -1 ? -1 * (65536 - oriValue) : oriValue)
							+ "";

					object.setValue(value);
					offset += 2;

					newData = Arrays.copyOfRange(data, offset, offset + 7);
					object.setTimeStamp(parseTimestamp(newData));
					offset += 7;

					object.setDescripWords(byte2Hex(data[offset]));
					offset++;
				}

				break;
			default:
				break;
			}

			infoObjs.add(object);
		}
	}

	/**
	 * 
	 * @Title: parseSyncTime
	 * @Description: 时间同步解析
	 * @param
	 * @return
	 * @throws
	 */
	protected void parseSyncTime(InfoObjectAddrLengthEnum infoObjAddrLen) {

		InfoObject object = new InfoObject();

		// 信息体地址
		int addr = 0;
		switch (infoObjAddrLen) {
		case LENGTH_INFO_ADDR_2:
			addr = byte2Decimal(data[offset + 1]) * 256
					+ byte2Decimal(data[offset]);
			offset += 2;
			break;
		case LENGTH_INFO_ADDR_3:
			addr = byte2Decimal(data[offset + 2]) * 256 * 256
					+ byte2Decimal(data[offset + 1]) * 256
					+ byte2Decimal(data[offset]);
			offset += 3;
			break;
		}
		object.setAddr(addr);

		// 7个字节8位位组的二进制时间
		byte[] newData = Arrays.copyOfRange(data, offset, offset + 7);
		object.setTimeStamp(parseTimestamp(newData));
		offset += 7;

		infoObjs.add(object);
	}

	/**
	 * 
	 * @Title: parseSingleParamRead
	 * @Description: 读单个参数解析
	 * @param
	 * @return
	 * @throws
	 */
	protected void parseSingleParamReadAndWrite(
			InfoObjectAddrLengthEnum infoObjAddrLen) {

		InfoObject object = new InfoObject();

		// 信息体地址
		int addr = 0;
		int infoObjLen = 0;
		switch (infoObjAddrLen) {
		case LENGTH_INFO_ADDR_2:
			addr = byte2Decimal(data[offset + 1]) * 256
					+ byte2Decimal(data[offset]);
			offset += 2;
			infoObjLen = 2;
			break;
		case LENGTH_INFO_ADDR_3:
			addr = byte2Decimal(data[offset + 2]) * 256 * 256
					+ byte2Decimal(data[offset + 1]) * 256
					+ byte2Decimal(data[offset]);
			offset += 3;
			infoObjLen = 3;
			break;
		}
		object.setAddr(addr);

		if (20525 == addr) {
			String value = ConvertInXBaseUtil.byte2Decimal(data[offset]) + "."
					+ ConvertInXBaseUtil.byte2Decimal(data[offset + 1]);
			offset += 2;

			offset += infoObjLen;
			value += "." + ConvertInXBaseUtil.byte2Decimal(data[offset]) + "."
					+ ConvertInXBaseUtil.byte2Decimal(data[offset + 1]);
			offset += 2;

			offset += infoObjLen;
			value += ":"
					+ (byte2Decimal(data[offset + 1]) * 256 + byte2Decimal(data[offset]));
			offset += 2;

			object.setValue(value);
		} else if (20528 == addr) {

			String value = ConvertInXBaseUtil.byte2Hex(data[offset])
					+ ConvertInXBaseUtil.byte2Hex(data[offset + 1]);
			offset += 2;

			offset += infoObjLen;
			value += ConvertInXBaseUtil.byte2Hex(data[offset])
					+ ConvertInXBaseUtil.byte2Hex(data[offset + 1]);
			offset += 2;

			offset += infoObjLen;
			value += ConvertInXBaseUtil.byte2Hex(data[offset])
					+ ConvertInXBaseUtil.byte2Hex(data[offset + 1]);
			offset += 2;

			offset += infoObjLen;
			value += ConvertInXBaseUtil.byte2Hex(data[offset])
					+ ConvertInXBaseUtil.byte2Hex(data[offset + 1]);
			offset += 2;

			value = ConvertInXBaseUtil.decodeAscii(value.toUpperCase());
			object.setValue(value);
		} else {

			int symbol = data[offset + 1] >> 8; // 最高位为1表示负数，为0表示正数
			int oriValue = byte2Decimal(data[offset + 1]) * 256
					+ byte2Decimal(data[offset]);
			int value = (symbol == -1 ? -1 * (65536 - oriValue) : oriValue);

			object.setValue(Integer.toString(value));
			offset += 2;
		}
		infoObjs.add(object);
	}

	/**
	 * 
	 * @Title: parseRecordingData
	 * @Description: 故障录波上报解析
	 * @param
	 * @return
	 * @throws
	 */
	protected void parseRecordingData(InfoObjectAddrLengthEnum infoObjAddrLen) {

		recordingData = new RecordingData();
		// 录波数据帧号 1字节
		int currFrameNo = byte2Decimal(data[offset]);
		recordingData.setCurrFrameNo(currFrameNo);
		offset++;

		// 录波数据总帧数 1字节
		int totalFrames = byte2Decimal(data[offset]);
		recordingData.setTotalFrames(totalFrames);
		offset++;

		// 信息体地址
		int addr = 0;
		switch (infoObjAddrLen) {
		case LENGTH_INFO_ADDR_2:
			addr = byte2Decimal(data[offset + 1]) * 256
					+ byte2Decimal(data[offset]);
			offset += 2;
			break;
		case LENGTH_INFO_ADDR_3:
			addr = byte2Decimal(data[offset + 2]) * 256 * 256
					+ byte2Decimal(data[offset + 1]) * 256
					+ byte2Decimal(data[offset]);
			offset += 3;
			break;
		}
		recordingData.setAddr(addr);

		// 第一个数据... 第N个数据
		List<Integer> dataList = new ArrayList<Integer>();
		for (int i = offset; i < data.length - 22; i += 2) {
			int temp = byte2Decimal(data[offset + 1]) * 256
					+ byte2Decimal(data[offset]);

			int symbol = data[offset + 1] >> 8; // 最高位为1表示负数，为0表示正数
			temp = (symbol == -1 ? -1 * (65536 - temp) : temp);
			dataList.add(temp);

			offset += 2;
		}
		recordingData.setDataList(dataList);

		// 采样间隔
		int samplInterval = byte2Decimal(data[offset + 1]) * 256
				+ byte2Decimal(data[offset]);
		recordingData.setSamplInterval(samplInterval);
		offset += 2;

		// 录波起始时标
		byte[] temp = Arrays.copyOfRange(data, offset, offset + 7);
		String timestamp = parseTimestamp(temp);
		recordingData.setRTimestamp(timestamp);
		offset += 7;

		// 录波起始时标微秒数
		int ms = byte2Decimal(data[offset + 1]) * 256
				+ byte2Decimal(data[offset]);
		recordingData.setRMs(formatMSecond(ms));
		offset += 2;

		// 第一个数据时标
		temp = Arrays.copyOfRange(data, offset, offset + 7);
		timestamp = parseTimestamp(temp);
		recordingData.setFTimestamp(timestamp);
		offset += 7;

		// 第一个数据时标微秒数
		ms = byte2Decimal(data[offset + 1]) * 256 + byte2Decimal(data[offset]);
		recordingData.setFMs(formatMSecond(ms));
		offset += 2;
	}

	/**
	 * 
	 * @Title: parseFileReady
	 * @Description: 文件准备就绪解析
	 * @param
	 * @return
	 * @throws
	 */
	protected void parseFileReady(InfoObjectAddrLengthEnum infoObjAddrLen) {

		fileInfoObject = new FileInfoObject();

		// 信息体地址
		int addr = 0;
		switch (infoObjAddrLen) {
		case LENGTH_INFO_ADDR_2:
			addr = byte2Decimal(data[offset + 1]) * 256
					+ byte2Decimal(data[offset]);
			offset += 2;
			break;
		case LENGTH_INFO_ADDR_3:
			addr = byte2Decimal(data[offset + 2]) * 256 * 256
					+ byte2Decimal(data[offset + 1]) * 256
					+ byte2Decimal(data[offset]);
			offset += 3;
			break;
		}
		fileInfoObject.setAddr(addr);

		// 计算文件名长度
		int msgLen = byte2Decimal(data[2]) * 256 + byte2Decimal(data[1]); // 整个报文长度
		fileNameLen = msgLen - 8 - 4; // 减去除设备地址
		switch (infoObjAddrLen) {
		case LENGTH_INFO_ADDR_2:
			fileNameLen -= 2;
			break;
		case LENGTH_INFO_ADDR_3:
			fileNameLen -= 3;
			break;
		}

		// 文件名
		String fileName = "";
		for (int i = offset; i < fileNameLen + offset; i++) {
			fileName += byte2Hex(data[i]);
		}
		fileInfoObject.setFileName(ConvertInXBaseUtil.decodeAscii(fileName
				.toUpperCase()));
		offset += fileNameLen;

		// 文件长度
		int fileLength = byte2Decimal(data[offset + 2]) * 256 * 256
				+ byte2Decimal(data[offset + 1]) * 256
				+ byte2Decimal(data[offset]);
		fileInfoObject.setFileLength(fileLength);
		offset += 3;

		// 文件准备就绪限定词FRQ
		int frq = byte2Decimal(data[offset]);
		fileInfoObject.setFrq(frq);
		offset++;
	}

	/**
	 * 
	 * @Title: parseSectionReady
	 * @Description: 节准备就绪解析
	 * @param
	 * @return
	 * @throws
	 */
	protected void parseSectionReady(InfoObjectAddrLengthEnum infoObjAddrLen)
			throws Exception {

		sectionInfoObject = new SectionInfoObject();

		// 信息体地址
		int addr = 0;
		switch (infoObjAddrLen) {
		case LENGTH_INFO_ADDR_2:
			addr = byte2Decimal(data[offset + 1]) * 256
					+ byte2Decimal(data[offset]);
			offset += 2;
			break;
		case LENGTH_INFO_ADDR_3:
			addr = byte2Decimal(data[offset + 2]) * 256 * 256
					+ byte2Decimal(data[offset + 1]) * 256
					+ byte2Decimal(data[offset]);
			offset += 3;
			break;
		}
		sectionInfoObject.setAddr(addr);

		// 文件名
		String fileName = "";
		for (int i = offset; i < FileInfoObject.FILE_NAME_LENGTH + offset; i++) {
			fileName += byte2Hex(data[i]);
		}
		sectionInfoObject.setFileName(ConvertInXBaseUtil.decodeAscii(fileName
				.toUpperCase()));
		offset += FileInfoObject.FILE_NAME_LENGTH;

		// 节名
		int sectionName = byte2Decimal(data[offset]);
		sectionInfoObject.setSectionName(sectionName);
		offset++;

		// 节长度
		int sectionLength = byte2Decimal(data[offset + 2]) * 256 * 256
				+ byte2Decimal(data[offset + 1]) * 256
				+ byte2Decimal(data[offset]);
		sectionInfoObject.setSectionLength(sectionLength);
		offset += 3;

		// 节准备就绪限定词SRQ
		int srq = byte2Decimal(data[offset]);
		sectionInfoObject.setSrq(srq);
		offset++;
	}

	/**
	 * 
	 * @Title: parsePieceData
	 * @Description: 段数据解析
	 * @param
	 * @return
	 * @throws
	 */
	protected void parsePieceData(InfoObjectAddrLengthEnum infoObjAddrLen)
			throws Exception {

		pieceDataInfoObject = new PieceDataInfoObject();

		// 信息体地址
		int addr = 0;
		switch (infoObjAddrLen) {
		case LENGTH_INFO_ADDR_2:
			addr = byte2Decimal(data[offset + 1]) * 256
					+ byte2Decimal(data[offset]);
			offset += 2;
			break;
		case LENGTH_INFO_ADDR_3:
			addr = byte2Decimal(data[offset + 2]) * 256 * 256
					+ byte2Decimal(data[offset + 1]) * 256
					+ byte2Decimal(data[offset]);
			offset += 3;
			break;
		}
		pieceDataInfoObject.setAddr(addr);

		// 计算文件名长度
		int msgLenWithHeadTail = data.length;
		int tempOffset = 4 + 8 + 1;
		switch (infoObjAddrLen) {
		case LENGTH_INFO_ADDR_2:
			tempOffset += 2;
			break;
		case LENGTH_INFO_ADDR_3:
			tempOffset += 3;
			break;
		}
		if (byte2Decimal(data[tempOffset + 32 + 1]) * 256
				+ byte2Decimal(data[tempOffset + 32]) == msgLenWithHeadTail
				- (tempOffset + 32) - 2 - 2) { // 只能试探性的计算
			fileNameLen = 32;
		} else {
			fileNameLen = 8;
		}

		// 文件名
		String fileName = "";
		for (int i = offset; i < fileNameLen + offset; i++) {
			fileName += byte2Hex(data[i]);
		}
		pieceDataInfoObject.setFileName(ConvertInXBaseUtil.decodeAscii(fileName
				.toUpperCase()));
		offset += fileNameLen;

		// 节名
		int sectionName = byte2Decimal(data[offset]);
		pieceDataInfoObject.setSectionName(sectionName);
		offset++;

		// 段长度
		int pieceLength = byte2Decimal(data[offset + 1]) * 256
				+ byte2Decimal(data[offset]);
		pieceDataInfoObject.setPieceLength(pieceLength);
		offset += 2;

		// 段数据
		pieceDataInfoObject.setData(new String(Arrays.copyOfRange(data, offset,
				data.length - 2), "iso-8859-1"));
		offset = data.length - 2;
	}

	/**
	 * 
	 * @Title: parseLastSectionOrPiece
	 * @Description: 最后节和段解析
	 * @param
	 * @return
	 * @throws
	 */
	protected void parseLastSectionOrPiece(
			InfoObjectAddrLengthEnum infoObjAddrLen) throws Exception {

		sectionInfoObject = new SectionInfoObject();

		// 信息体地址
		int addr = 0;
		switch (infoObjAddrLen) {
		case LENGTH_INFO_ADDR_2:
			addr = byte2Decimal(data[offset + 1]) * 256
					+ byte2Decimal(data[offset]);
			offset += 2;
			break;
		case LENGTH_INFO_ADDR_3:
			addr = byte2Decimal(data[offset + 2]) * 256 * 256
					+ byte2Decimal(data[offset + 1]) * 256
					+ byte2Decimal(data[offset]);
			offset += 3;
			break;
		}
		sectionInfoObject.setAddr(addr);

		// 计算文件名长度
		int msgLen = byte2Decimal(data[2]) * 256 + byte2Decimal(data[1]); // 整个报文长度
		fileNameLen = msgLen - 8 - 3; // 减去除设备地址
		switch (infoObjAddrLen) {
		case LENGTH_INFO_ADDR_2:
			fileNameLen -= 2;
			break;
		case LENGTH_INFO_ADDR_3:
			fileNameLen -= 3;
			break;
		}

		// 文件名
		String fileName = "";
		for (int i = offset; i < fileNameLen + offset; i++) {
			fileName += byte2Hex(data[i]);
		}
		sectionInfoObject.setFileName(ConvertInXBaseUtil.decodeAscii(fileName
				.toUpperCase()));
		offset += fileNameLen;

		// 节名
		int sectionName = byte2Decimal(data[offset]);
		sectionInfoObject.setSectionName(sectionName);
		offset++;

		// 最后的段或最后的节限定词LSQ
		int srq = byte2Decimal(data[offset]);
		sectionInfoObject.setSrq(srq);
		offset++;

		offset++; // 一个节的校验和
	}

	/**
	 * 
	 * @Title: parseFileList
	 * @Description: 文件目录解析
	 * @param
	 * @return
	 * @throws
	 */
	protected void parseFileList(InfoObjectAddrLengthEnum infoObjAddrLen)
			throws Exception {

		fileListInfoObject = new FileListInfoObject();

		// 信息体地址
		int addr = 0;
		switch (infoObjAddrLen) {
		case LENGTH_INFO_ADDR_2:
			addr = byte2Decimal(data[offset + 1]) * 256
					+ byte2Decimal(data[offset]);
			offset += 2;
			break;
		case LENGTH_INFO_ADDR_3:
			addr = byte2Decimal(data[offset + 2]) * 256 * 256
					+ byte2Decimal(data[offset + 1]) * 256
					+ byte2Decimal(data[offset]);
			offset += 3;
			break;
		}
		fileListInfoObject.setAddr(addr);

		// 计算文件名长度
		int msgLen = byte2Decimal(data[2]) * 256 + byte2Decimal(data[1]); // 整个报文长度
		int tempLen = msgLen - 8; // 减去除设备地址
		switch (infoObjAddrLen) {
		case LENGTH_INFO_ADDR_2:
			tempLen -= 2;
			break;
		case LENGTH_INFO_ADDR_3:
			tempLen -= 3;
			break;
		}
		fileNameLen = tempLen / number - 3 - 1 - 7;

		List<FileInfoObject> fileList = new ArrayList<FileInfoObject>();
		for (int i = 0; i < number; i++) {
			FileInfoObject object = new FileInfoObject();
			// 文件名
			String fileName = "";
			for (int j = offset; j < fileNameLen + offset; j++) {
				fileName += byte2Hex(data[j]);
			}
			object.setFileName(ConvertInXBaseUtil.decodeAscii(fileName
					.toUpperCase()));
			offset += fileNameLen;

			// 文件长度
			int fileLength = byte2Decimal(data[offset + 2]) * 256 * 256
					+ byte2Decimal(data[offset + 1]) * 256
					+ byte2Decimal(data[offset]);
			object.setFileLength(fileLength);
			offset += 3;

			// 文件的状态SOF
			int sof = byte2Decimal(data[offset]);
			object.setSof(sof);
			offset++;

			// 时标
			byte[] temp = Arrays.copyOfRange(data, offset, offset + 7);
			String timestamp = parseTimestamp(temp);
			object.setTimestamp(timestamp);
			offset += 7;

			fileList.add(object);
		}

		fileListInfoObject.setFileList(fileList);

		for (FileInfoObject fileInfoObject : fileListInfoObject.getFileList()) {
			Map<String, String> map = new TreeMap<String, String>();
			map.put("id", ConvertInXBaseUtil.encodeAscii(fileInfoObject
					.getFileName()));
			map.put("text", fileInfoObject.getFileName().trim());
			System.err.println(map);

		}

	}

	/**
	 * 
	 * @Title: parseRemoteControl
	 * @Description: 遥控解析
	 * @param
	 * @return
	 * @throws
	 */
	protected void parseRemoteControl(InfoObjectAddrLengthEnum infoObjAddrLen)
			throws Exception {

		remoteControlInfoObject = new RemoteControlInfoObject();

		// 信息体地址
		int addr = 0;
		switch (infoObjAddrLen) {
		case LENGTH_INFO_ADDR_2:
			addr = byte2Decimal(data[offset + 1]) * 256
					+ byte2Decimal(data[offset]);
			offset += 2;
			break;
		case LENGTH_INFO_ADDR_3:
			addr = byte2Decimal(data[offset + 2]) * 256 * 256
					+ byte2Decimal(data[offset + 1]) * 256
					+ byte2Decimal(data[offset]);
			offset += 3;
			break;
		}
		remoteControlInfoObject.setAddr(addr);

		// 单命令
		String sco = byte2Hex(data[offset]);
		remoteControlInfoObject.setSco(sco);
		offset++;
	}

	/**
	 * 
	 * @Title: parseSettingAreaRead
	 * @Description: 读当前定值区解析
	 * @param
	 * @return
	 * @throws
	 */
	protected void parseSettingAreaRead(InfoObjectAddrLengthEnum infoObjAddrLen) {

		currSettingArea = new CurrSettingArea();

		int addr = 0;
		switch (infoObjAddrLen) {
		case LENGTH_INFO_ADDR_2:
			addr = byte2Decimal(data[offset + 1]) * 256
					+ byte2Decimal(data[offset]);
			offset += 2;
			break;
		case LENGTH_INFO_ADDR_3:
			addr = byte2Decimal(data[offset + 2]) * 256 * 256
					+ byte2Decimal(data[offset + 1]) * 256
					+ byte2Decimal(data[offset]);
			offset += 3;
			break;
		}
		currSettingArea.setAddr(addr);

		// 当前定值区区号SN1 2字节
		int sn = byte2Decimal(data[offset + 1]) * 256
				+ byte2Decimal(data[offset]);
		currSettingArea.setCurrSN(sn);
		offset += 2;

		// 终端支持的最小定值区号SN2 2字节
		sn = byte2Decimal(data[offset + 1]) * 256 + byte2Decimal(data[offset]);
		currSettingArea.setMinSN(sn);
		offset += 2;

		// 终端支持的最大定值区号SN3 2字节
		sn = byte2Decimal(data[offset + 1]) * 256 + byte2Decimal(data[offset]);
		currSettingArea.setMaxSN(sn);
		offset += 2;
	}

	/**
	 * 
	 * @Title: parseSettingAreaWrite
	 * @Description: 切换定值区解析
	 * @param
	 * @return
	 * @throws
	 */
	protected void parseSettingAreaWrite(InfoObjectAddrLengthEnum infoObjAddrLen) {

		currSettingArea = new CurrSettingArea();

		int addr = 0;
		switch (infoObjAddrLen) {
		case LENGTH_INFO_ADDR_2:
			addr = byte2Decimal(data[offset + 1]) * 256
					+ byte2Decimal(data[offset]);
			offset += 2;
			break;
		case LENGTH_INFO_ADDR_3:
			addr = byte2Decimal(data[offset + 2]) * 256 * 256
					+ byte2Decimal(data[offset + 1]) * 256
					+ byte2Decimal(data[offset]);
			offset += 3;
			break;
		}
		currSettingArea.setAddr(addr);

		// 定值区号SN 2字节
		int sn = byte2Decimal(data[offset + 1]) * 256
				+ byte2Decimal(data[offset]);
		currSettingArea.setCurrSN(sn);
		offset += 2;
	}

	/**
	 * 
	 * @Title: parseParametersRead
	 * @Description: 读取定值参数解析
	 * @param
	 * @return
	 * @throws
	 */
	protected void parseParametersRead(InfoObjectAddrLengthEnum infoObjAddrLen)
			throws Exception {

		// 定值区号SN 2字节
		int sn = byte2Decimal(data[offset + 1]) * 256
				+ byte2Decimal(data[offset]);
		offset += 2;

		// 参数特征标识
		int tag = byte2Decimal(data[offset]);
		offset++;

		for (int i = 0; i < number; i++) {
			Parameter parameter = new Parameter();
			// 信息体地址
			int addr = 0;
			switch (infoObjAddrLen) {
			case LENGTH_INFO_ADDR_2:
				addr = byte2Decimal(data[offset + 1]) * 256
						+ byte2Decimal(data[offset]);
				offset += 2;
				break;
			case LENGTH_INFO_ADDR_3:
				addr = byte2Decimal(data[offset + 2]) * 256 * 256
						+ byte2Decimal(data[offset + 1]) * 256
						+ byte2Decimal(data[offset]);
				offset += 3;
				break;
			}
			parameter.setAddr(addr);

			int tagType = byte2Decimal(data[offset]);
			parameter.setTagType(tagType);
			offset++;

			int length = ConvertInXBaseUtil.byte2Decimal(data[offset]);
			parameter.setLength(length);
			offset++;

			String value = "";
			if (4 == tagType) {
				for (int j = offset; j < length + offset; j++) {
					value += byte2Hex(data[j]);
				}
				parameter.setValue(ConvertInXBaseUtil.decodeAscii(value
						.toUpperCase()));
			} else {
				for (int j = offset; j < length + offset; j++) {
					value += byte2Hex(data[j]);
				}
				parameter.setValue(value);
			}
			offset += length;

			parameters.add(parameter);
		}
	}

	/**
	 * 
	 * @Title: formatMSecond
	 * @Description: 格式化毫秒/微秒
	 * @param
	 * @return
	 * @throws
	 */
	protected String formatMSecond(int second) {

		String ms = Integer.toString(second);
		int len = ms.length();
		for (int j = len; j < 3; j++) {
			ms = "0" + ms;
		}

		return ms;
	}

	/**
	 * 
	 * @Title: parseTimestamp
	 * @Description: 解析时标CP56Time2a
	 * @param
	 * @return
	 * @throws
	 */
	protected String parseTimestamp(byte[] temp) {

		int ms = hex2Decimal(byte2Hex(temp[1]) + byte2Hex(temp[0]));
		String second = Integer.toString(ms / 1000);
		String mis = Integer.toString(ms % 1000);
		int len = mis.length();
		for (int j = len; j < 3; j++) {
			mis = "0" + mis;
		}
		String minuter = Integer.toString(byte2Decimal(temp[2]));
		String hour = Integer.toString(byte2Decimal(temp[3]));
		String bin = decimal2Binary(byte2Decimal(temp[4]));
		String day = Integer.toString(binary2Decimal("000" + bin.substring(3)));
		String month = Integer.toString(byte2Decimal(temp[5]));
		String year = Integer.toString((byte2Decimal(temp[6]) + 2000));

		// int year = DateTimeUtil.getYear(new Date());
		String time = new StringBuffer().append(year).append("-")
				.append(month.length() == 1 ? "0" + month : month).append("-")
				.append(day.length() == 1 ? "0" + day : day).append(" ")
				.append(hour.length() == 1 ? "0" + hour : hour).append(":")
				.append(minuter.length() == 1 ? "0" + minuter : minuter)
				.append(":")
				.append(second.length() == 1 ? "0" + second : second)
				.append(".").append(mis).toString();

		return time;
	}

	/**
	 * 
	 * @Title: parseStartCharacter
	 * @Description: 解析起始字符
	 * @param
	 * @return
	 * @throws
	 */
	protected void parseStartCharacter() {
		String temp = byte2Hex(data[offset]);
		setStartCharacter(temp);

		offset++;
	}

	/**
	 * 
	 * @Title: parseLength
	 * @Description: 解析报文长度
	 * @param
	 * @return
	 * @throws
	 */
	protected void parseLength() {
		int length = byte2Decimal(data[offset]);
		setLength(length);

		offset++;
	}

	/**
	 * 
	 * @Title: parseControlField
	 * @Description: 解析控制域
	 * @param
	 * @return
	 * @throws
	 */
	protected void parseControlField(ProtocolEnum.TypeEnum type,
			ControlFieldLengthEnum controlFieldLen) {

		String temp = null;
		switch (type) {
		case IEC_101:

			offset += 2; // 长度偏移

			switch (controlFieldLen) {
			case LENGTH_CONTROL_FIELD_1:
				temp = byte2Hex(data[offset]);
				offset++;
				break;
			case LENGTH_CONTROL_FIELD_4:
				temp = byte2Hex(data[offset + 3]) + byte2Hex(data[offset + 2])
						+ byte2Hex(data[offset + 1]) + byte2Hex(data[offset]);
				offset += 4;
				break;
			}
			setControlField(temp);

			break;
		case IEC_104:
			switch (controlFieldLen) {
			case LENGTH_CONTROL_FIELD_1:
				temp = byte2Hex(data[offset]);
				offset++;
				break;
			case LENGTH_CONTROL_FIELD_4:
				temp = byte2Hex(data[offset + 3]) + byte2Hex(data[offset + 2])
						+ byte2Hex(data[offset + 1]) + byte2Hex(data[offset]);
				offset += 4;
				break;
			}
			setControlField(temp);
			break;
		}
	}

	/**
	 * 
	 * @Title: parseAddressField
	 * @Description: 解析地址域
	 * @param
	 * @return
	 * @throws
	 */
	protected void parseAddressField(ProtocolEnum.TypeEnum type,
			LinkAddrLengthEnum linkAddrLen) {

		String temp = null;
		switch (type) {
		case IEC_101:
			switch (linkAddrLen) {
			case LENGTH_LINK_ADDR_2:
				temp = byte2Hex(data[offset + 1]) + byte2Hex(data[offset]);
				offset += 2;
				break;
			case LENGTH_LINK_ADDR_4:
				temp = byte2Hex(data[offset + 3]) + byte2Hex(data[offset + 2])
						+ byte2Hex(data[offset + 1]) + byte2Hex(data[offset]);
				offset += 4;
				break;
			case LENGTH_LINK_ADDR_6:

				temp = Character.toString((char) data[offset])
						+ Character.toString((char) data[offset + 1])
						+ byte2Hex(data[offset + 3])
						+ byte2Hex(data[offset + 2])
						+ byte2Hex(data[offset + 5])
						+ byte2Hex(data[offset + 4]);
				offset += 6;
				break;
			}

			setAddressField(temp);
			break;
		}
	}

	/**
	 * 
	 * @Title: parseTypeIdentity
	 * @Description: 解析类型标识
	 * @param
	 * @return
	 * @throws
	 */
	protected void parseTypeIdentity() {
		int ti = byte2Decimal(data[offset]);
		setTypeIdentity(ti);

		offset++;
	}

	/**
	 * 
	 * @Title: parseVarStructQualifier
	 * @Description: 解析可变结构限定词
	 * @param
	 * @return
	 * @throws
	 */
	protected void parseVarStructQualifier() {
		// 单个或顺序 0: 单个；1: 顺序
		int sq = byte2Decimal(data[offset]) > 128 ? 1 : 0;// 最高位
		setSingleOrQueue(sq);

		int number = data[offset] & 0x7F;// 除最高位外，信息点数目
		setNumber(number);

		offset++;
	}

	/**
	 * 
	 * @Title: parseCause
	 * @Description: 解析传输原因
	 * @param
	 * @return
	 * @throws
	 */
	protected void parseCause(COTLengthEnum cotLen) {

		int cause = 0;
		switch (cotLen) {
		case LENGTH_COT_1:
			cause = byte2Decimal(data[offset]);
			offset++;
			break;
		case LENGTH_COT_2:
			cause = byte2Decimal(data[offset + 1]) * 256
					+ byte2Decimal(data[offset]);
			offset += 2;
			break;
		}

		setCause(cause);
	}

	/**
	 * 
	 * @Title: parseASDU
	 * @Description:解析ASDU
	 * @param
	 * @return
	 * @throws
	 */
	protected void parseASDU(AsduPublicAddrLengthEnum asduAddrLen) {

		String temp = null;
		switch (asduAddrLen) {
		case LENGTH_ASDU_ADDR_2:
			temp = byte2Hex(data[offset + 1]) + byte2Hex(data[offset]);
			offset += 2;
			break;
		case LENGTH_ASDU_ADDR_4:
			// temp = byte2Hex(data[offset + 3]) + byte2Hex(data[offset + 2])
			// + byte2Hex(data[offset + 1]) + byte2Hex(data[offset]);
			temp = Character.toString((char) data[offset])
					+ Character.toString((char) data[offset + 1])
					+ Character.toString((char) data[offset + 2])
					+ Character.toString((char) data[offset + 3]);
			offset += 4;
			break;
		}

		setAsduPublicAddr(temp);
	}

	/**
	 * 
	 * @Title: parseSumCheck
	 * @Description: 解析校验和
	 * @param
	 * @return
	 * @throws
	 */
	protected void parseSumCheck(ProtocolEnum.TypeEnum type) {

		// 帧校验和结束字符
		switch (type) {
		case IEC_101:

			setSumCheck(byte2Hex(data[offset]));
			offset++;
		}
	}

	/**
	 * 
	 * @Title: parseFinalCharacter
	 * @Description: 解析结束字符
	 * @param
	 * @return
	 * @throws
	 */
	protected void parseFinalCharacter(ProtocolEnum.TypeEnum type) {
		switch (type) {
		case IEC_101:
			setFinalCharacter(byte2Hex(data[offset]));
			offset++;
		}
	}

	public String getStartCharacter() {
		return startCharacter;
	}

	public void setStartCharacter(String startCharacter) {
		this.startCharacter = startCharacter;
	}

	public int getLength() {
		return length;
	}

	public void setLength(int length) {
		this.length = length;
	}

	public String getControlField() {
		return controlField;
	}

	public void setControlField(String controlField) {
		this.controlField = controlField;
	}

	public String getAddressField() {
		return addressField;
	}

	public void setAddressField(String addressField) {
		this.addressField = addressField;
	}

	public int getTypeIdentity() {
		return typeIdentity;
	}

	public void setTypeIdentity(int typeIdentity) {
		this.typeIdentity = typeIdentity;
	}

	public int getSingleOrQueue() {
		return singleOrQueue;
	}

	public void setSingleOrQueue(int singleOrQueue) {
		this.singleOrQueue = singleOrQueue;
	}

	public int getNumber() {
		return number;
	}

	public void setNumber(int number) {
		this.number = number;
	}

	public int getCause() {
		return cause;
	}

	public void setCause(int cause) {
		this.cause = cause;
	}

	public String getAsduPublicAddr() {
		return asduPublicAddr;
	}

	public void setAsduPublicAddr(String asduPublicAddr) {
		this.asduPublicAddr = asduPublicAddr;
	}

	public List<InfoObject> getInfoObjs() {
		return infoObjs;
	}

	public void setInfoObjs(List<InfoObject> infoObjs) {
		this.infoObjs = infoObjs;
	}

	public String getSumCheck() {
		return sumCheck;
	}

	public void setSumCheck(String sumCheck) {
		this.sumCheck = sumCheck;
	}

	public String getFinalCharacter() {
		return finalCharacter;
	}

	public void setFinalCharacter(String finalCharacter) {
		this.finalCharacter = finalCharacter;
	}

	public RecordingData getRecordingData() {
		return recordingData;
	}

	public void setRecordingData(RecordingData recordingData) {
		this.recordingData = recordingData;
	}

	public FileInfoObject getFileInfoObject() {
		return fileInfoObject;
	}

	public void setFileInfoObject(FileInfoObject fileInfoObject) {
		this.fileInfoObject = fileInfoObject;
	}

	public SectionInfoObject getSectionInfoObject() {
		return sectionInfoObject;
	}

	public void setSectionInfoObject(SectionInfoObject sectionInfoObject) {
		this.sectionInfoObject = sectionInfoObject;
	}

	public PieceDataInfoObject getPieceDataInfoObject() {
		return pieceDataInfoObject;
	}

	public void setPieceDataInfoObject(PieceDataInfoObject pieceDataInfoObject) {
		this.pieceDataInfoObject = pieceDataInfoObject;
	}

	public RemoteControlInfoObject getRemoteControlInfoObject() {
		return remoteControlInfoObject;
	}

	public void setRemoteControlInfoObject(
			RemoteControlInfoObject remoteControlInfoObject) {
		this.remoteControlInfoObject = remoteControlInfoObject;
	}

	public FileListInfoObject getFileListInfoObject() {
		return fileListInfoObject;
	}

	public void setFileListInfoObject(FileListInfoObject fileListInfoObject) {
		this.fileListInfoObject = fileListInfoObject;
	}

	public CurrSettingArea getCurrSettingArea() {
		return currSettingArea;
	}

	public void setCurrSettingArea(CurrSettingArea currSettingArea) {
		this.currSettingArea = currSettingArea;
	}

	public List<Parameter> getParameters() {
		return parameters;
	}

	public void setParameters(List<Parameter> parameters) {
		this.parameters = parameters;
	}
}